package com.lau.dicttranslator.service.impl;

import com.lau.dicttranslator.repository.DictDataMapper;
import com.lau.dicttranslator.service.DictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.time.Duration;

/**
 * 字典服务实现类
 */
@Service
@Slf4j
public class DictServiceImpl implements DictService {
    
    @Autowired
    private DictDataMapper dictDataMapper;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    // 缓存键前缀
    private static final String DICT_CACHE_PREFIX = "dict:cache:";
    private static final String ENUM_CACHE_PREFIX = "enum:cache:";
    
    /**
     * 根据字典类型和键值获取标签（支持缓存）
     */
    @Override
    @Cacheable(value = "dictCache", key = "#dictType + ':' + #dictKey", unless = "#result == null")
    public String getDictLabel(String dictType, String dictKey) {
        return getDictLabel(dictType, dictKey, true, 3600L);
    }
    
    /**
     * 根据字典类型和键值获取标签（支持动态缓存配置）
     */
    @Override
    public String getDictLabel(String dictType, String dictKey, boolean enableCache, long cacheExpire) {
        if (dictType == null || dictKey == null) {
            return null;
        }
        
        String cacheKey = DICT_CACHE_PREFIX + dictType + ":" + dictKey;
        
        // 如果不启用缓存，直接查询数据库
        if (!enableCache) {
            log.debug("缓存已禁用，直接查询数据库 - dictType: {}, dictKey: {}", dictType, dictKey);
            return getDictLabelFromDatabase(dictType, dictKey);
        }
        
        // 启用缓存时，先尝试从Redis获取
        try {
            String cachedValue = redisTemplate.opsForValue().get(cacheKey);
            if (cachedValue != null) {
                log.debug("缓存命中 - cacheKey: {}, value: {}", cacheKey, cachedValue);
                return cachedValue;
            }
            
            log.debug("缓存未命中，查询数据库 - dictType: {}, dictKey: {}", dictType, dictKey);
            
        } catch (Exception e) {
            log.warn("Redis缓存读取失败，降级到数据库查询 - cacheKey: {}, error: {}", cacheKey, e.getMessage());
        }
        
        // 缓存未命中或读取失败，查询数据库
        String result = getDictLabelFromDatabase(dictType, dictKey);
        
        // 如果查询成功且启用缓存，将结果存入Redis
        if (result != null && enableCache) {
            try {
                if (cacheExpire > 0) {
                    redisTemplate.opsForValue().set(cacheKey, result, Duration.ofSeconds(cacheExpire));
                    log.debug("缓存已更新 - cacheKey: {}, value: {}, expire: {}s", cacheKey, result, cacheExpire);
                } else {
                    redisTemplate.opsForValue().set(cacheKey, result);
                    log.debug("缓存已更新（永不过期） - cacheKey: {}, value: {}", cacheKey, result);
                }
            } catch (Exception e) {
                log.warn("Redis缓存写入失败 - cacheKey: {}, error: {}", cacheKey, e.getMessage());
            }
        }
        
        return result;
    }
    
    /**
     * 根据枚举类名和键值获取标签（支持缓存）
     */
    @Override
    @Cacheable(value = "enumCache", key = "#enumClassName + ':' + #dictKey", unless = "#result == null")
    public String getEnumLabel(String enumClassName, String dictKey) {
        return getEnumLabel(enumClassName, dictKey, true, 3600L);
    }
    
    /**
     * 根据枚举类名和键值获取标签（支持动态缓存配置）
     */
    @Override
    public String getEnumLabel(String enumClassName, String dictKey, boolean enableCache, long cacheExpire) {
        if (enumClassName == null || dictKey == null) {
            return null;
        }
        
        String cacheKey = ENUM_CACHE_PREFIX + enumClassName + ":" + dictKey;
        
        // 如果不启用缓存，直接查询
        if (!enableCache) {
            log.debug("缓存已禁用，直接查询枚举 - enumClassName: {}, dictKey: {}", enumClassName, dictKey);
            return getEnumLabelDirect(enumClassName, dictKey);
        }
        
        // 启用缓存时，先尝试从Redis获取
        try {
            String cachedValue = redisTemplate.opsForValue().get(cacheKey);
            if (cachedValue != null) {
                log.debug("缓存命中 - cacheKey: {}, value: {}", cacheKey, cachedValue);
                return cachedValue;
            }
            
            log.debug("缓存未命中，查询枚举 - enumClassName: {}, dictKey: {}", enumClassName, dictKey);
            
        } catch (Exception e) {
            log.warn("Redis缓存读取失败，降级到直接查询 - cacheKey: {}, error: {}", cacheKey, e.getMessage());
        }
        
        // 缓存未命中或读取失败，直接查询枚举
        String result = getEnumLabelDirect(enumClassName, dictKey);
        
        // 如果查询成功且启用缓存，将结果存入Redis
        if (result != null && enableCache) {
            try {
                if (cacheExpire > 0) {
                    redisTemplate.opsForValue().set(cacheKey, result, Duration.ofSeconds(cacheExpire));
                    log.debug("缓存已更新 - cacheKey: {}, value: {}, expire: {}s", cacheKey, result, cacheExpire);
                } else {
                    redisTemplate.opsForValue().set(cacheKey, result);
                    log.debug("缓存已更新（永不过期） - cacheKey: {}, value: {}", cacheKey, result);
                }
            } catch (Exception e) {
                log.warn("Redis缓存写入失败 - cacheKey: {}, error: {}", cacheKey, e.getMessage());
            }
        }
        
        return result;
    }
    
    /**
     * 从数据库获取字典标签
     */
    private String getDictLabelFromDatabase(String dictType, String dictKey) {
        try {
            String result = dictDataMapper.findDictLabelByTypeAndKey(dictType, dictKey);
            log.debug("数据库查询结果 - dictType: {}, dictKey: {}, result: {}", dictType, dictKey, result);
            return result;
        } catch (Exception e) {
            log.error("获取字典标签失败，dictType: {}, dictKey: {}", dictType, dictKey, e);
            return null;
        }
    }
    
    /**
     * 直接获取枚举标签
     */
    private String getEnumLabelDirect(String enumClassName, String dictKey) {
        try {
            Class<?> enumClass = Class.forName(enumClassName);
            if (!enumClass.isEnum()) {
                log.warn("类 {} 不是枚举类型", enumClassName);
                return null;
            }
            
            // 通过反射调用 getNameByCode 方法
            Method method = enumClass.getMethod("getNameByCode", Integer.class);
            Integer code = Integer.valueOf(dictKey);
            String result = (String) method.invoke(null, code);
            log.debug("枚举查询结果 - enumClassName: {}, dictKey: {}, result: {}", enumClassName, dictKey, result);
            return result;
            
        } catch (Exception e) {
            log.error("获取枚举标签失败，enumClassName: {}, dictKey: {}", enumClassName, dictKey, e);
            return null;
        }
    }
    
    /**
     * 清除指定字典类型的缓存
     */
    public void clearDictCache(String dictType) {
        try {
            String pattern = DICT_CACHE_PREFIX + dictType + ":*";
            redisTemplate.delete(redisTemplate.keys(pattern));
            log.info("已清除字典缓存 - dictType: {}", dictType);
        } catch (Exception e) {
            log.error("清除字典缓存失败 - dictType: {}", dictType, e);
        }
    }
    
    /**
     * 清除指定枚举类的缓存
     */
    public void clearEnumCache(String enumClassName) {
        try {
            String pattern = ENUM_CACHE_PREFIX + enumClassName + ":*";
            redisTemplate.delete(redisTemplate.keys(pattern));
            log.info("已清除枚举缓存 - enumClassName: {}", enumClassName);
        } catch (Exception e) {
            log.error("清除枚举缓存失败 - enumClassName: {}", enumClassName, e);
        }
    }
    
    /**
     * 清除所有字典相关缓存
     */
    public void clearAllCache() {
        try {
            redisTemplate.delete(redisTemplate.keys(DICT_CACHE_PREFIX + "*"));
            redisTemplate.delete(redisTemplate.keys(ENUM_CACHE_PREFIX + "*"));
            log.info("已清除所有字典相关缓存");
        } catch (Exception e) {
            log.error("清除所有缓存失败", e);
        }
    }
} 